package com.demo.core.service.base.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.demo.core.dao.FunctionDao;
import com.demo.core.dao.MenuDao;
import com.demo.core.dao.RoleFunctionDao;
import com.demo.core.dao.SiteDao;
import com.demo.core.dao.SiteFunctionDao;
import com.demo.core.model.Function;
import com.demo.core.model.Menu;
import com.demo.core.model.Role;
import com.demo.core.model.RoleFunction;
import com.demo.core.model.Site;
import com.demo.core.model.SiteFunction;
import com.demo.core.model.support.converter.AdjacencyListToChainedObjectConverter;
import com.demo.core.service.base.MenuService;
import com.demo.core.service.exception.base.ObjectCreateException;

/**
 * 菜单服务实现类
 * @author ryuu.kk
 *
 */
public class MenuServiceImpl implements MenuService {

	/**
	 * 菜单数据访问结接口
	 */
	private MenuDao menuDao;
	
	/**
	 * 站点数据访问层接口
	 */
	private SiteDao siteDao;
	
	/**
	 * 功能数据访问接口
	 */
	private FunctionDao functionDao;
	
	/**
	 * 站点功能数据访问接口
	 */
	private SiteFunctionDao siteFunctionDao;
	
	/**
	 * 角色功能数据访问接口
	 */
	private RoleFunctionDao roleFunctionDao;
	
	
	@Override
	@Transactional
	public Long save(Menu menu) {
		Long siteId = menu.getSiteId();
		// 首先创建功能模型
		Function function = new Function();
		if (siteId == null) {
			throw new ObjectCreateException(menu, "SiteID can not null.") {
				/**
				 * 序列化ID
				 */
				private static final long serialVersionUID = 1L;
			};
		}
		if (menu.getSiteGroupId() == null) {
			Site site = siteDao.select(siteId);
			if (site == null) {
				throw new ObjectCreateException(menu, "Site is not exist.") {
					/**
					 * 序列化ID
					 */
					private static final long serialVersionUID = 1L;
				};
			}
			function.setSiteGroupId(site.getSiteGroupId());
		} else {
			function.setSiteGroupId(menu.getSiteGroupId());
		}
		function.setUrl(menu.getUrl());
		function.setIsAnonymous(menu.isAnonymous());
		function.setName(menu.getName());
		function.setStatus("RWD");
		function.setType(Function.URL);
		function.setTitle(menu.getTitle());
		if (menu.getPid() == null) {
			// 使用根节点(ID = 1)
			function.setPid(1L);
		} else {
			function.setPid(menu.getPid());
		}
		// 创建功能数据
		Long functionId = functionDao.insert(function);
		SiteFunction sf = new SiteFunction();
		sf.setEnabled(Boolean.TRUE);
		sf.setFunctionId(functionId);
		sf.setSiteId(siteId);
		sf.setStatus("RWD");
		sf.setPriority(0x01);
		// 为站点分配该功能
		Long sfId = siteFunctionDao.insert(sf);
		
		menu.setSiteFunctionId(sfId);
		
		List<Role> roleList = menu.getRoleList();
		RoleFunction rf = null;
		// 角色&需要授权访问。
		if (roleList != null && !menu.isAnonymous()) {
			for (Role r : roleList) {
				rf = new RoleFunction();
				rf.setRoleId(r.getId());
				rf.setSiteFunctionId(sfId);
				rf.setStatus("RWD");
				rf.setEnabled(Boolean.TRUE);
				// 为角色分配功能
				roleFunctionDao.insert(rf);
			}
		}
		return menuDao.insert(menu);
	}

	@Override
	public boolean exists(Long id) {
		return menuDao.exists(id);
	}

	@Override
	public void delete(Long menuId, Long siteId) {
		Map<String, Object> params = new HashMap<String, Object>(3);
		if (menuId == null || siteId == null) {
			return;
		}
		
		params.put("id", menuId);
		params.put("siteId", siteId);
		List<Menu> mList = menuDao.select(params);
		if (mList.size() > 0) {
			for(Menu m : mList) {
				// 级联删除function/sitefunction/menu数据
				functionDao.delete(m.getId());
			}
		}
	}
	
	@Override
	@Transactional
	public int update(Long id, Long siteId, Menu menu) {
		if (id == null) {
			return 0;
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", id);
		params.put("siteId", siteId);
		
		Function function = new Function();
		
		function.setUrl(menu.getUrl());
		function.setIsAnonymous(menu.isAnonymous());
		function.setName(menu.getName());
		function.setStatus("RWD");
		function.setType(Function.URL);
		function.setTitle(menu.getTitle());
		functionDao.update(function, params);
		
		//Menu menu = menuDao.select(params);
		// 角色&需要授权访问。
		RoleFunction rf = null;
		List<Role> roleList = menu.getRoleList();
		
		params.clear();
		params.put("siteId", siteId);
		params.put("siteFunctionId", menu.getSiteFunctionId());
		roleFunctionDao.delete(params);
		
		if (roleList != null && !menu.isAnonymous()) {
			for (Role r : roleList) {
				rf = new RoleFunction();
				rf.setRoleId(r.getId());
				rf.setSiteFunctionId(menu.getSiteFunctionId());
				rf.setStatus("RWD");
				rf.setEnabled(Boolean.TRUE);
				// 为角色分配功能
				roleFunctionDao.insert(rf);
			}
		}
		return menuDao.update(menu, params);
	}

	@Override
	public void enabled(Long id, Long siteId, Boolean enabled, String status) {
		if (id == null) {
			return;
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", id);
		params.put("siteId", siteId);
		Menu menu = new Menu();
		menu.setEnabled(enabled);
		menu.setStatus(status);
		menuDao.enabled(menu, params);
	}
	
	@Override
	public Menu find(Long menuId) {
		Map<String, Object> params = new HashMap<String, Object>(3);
		params.put("originalId", menuId);
		List<Menu> menuList = menuDao.select(params);
		return menuList.size() == 1 ? menuList.get(0) : null;
	}

	@Override
	public Menu find(Long funId, Long siteId) {
		Menu menu = menuDao.select(funId);
		if ( menu.getSiteId()!= null && menu.getSiteId().equals(siteId)) {
			return menu;
		} else {
			return null;
		}
	}

	@Override
	public List<Menu> findList(Long pid, Long siteId) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		params.put("pid", pid);
		params.put("siteId", siteId);
		return menuDao.select(params);
	}

	@Override
	public Menu tree(Long siteId) {
		return tree(null, siteId);
	}
	
	@Override
	public Menu tree(Long id, Long siteId) {
		Map<String, Object> params = new HashMap<String, Object>(5);
		params.put("id", id);
		params.put("siteId", siteId);
		List<Menu> menuList = menuDao.tree(params);
		return AdjacencyListToChainedObjectConverter.conver(menuList);
	}
	
	@Override
	public Menu tree(Long id, Long siteId, int...depths) {
		Map<String, Object> params = new HashMap<String, Object>(7);
		params.put("id", id);
		params.put("siteId", siteId);
		params.put("depthList", CollectionUtils.arrayToList(depths));
		List<Menu> menuList = menuDao.tree(params);
		return AdjacencyListToChainedObjectConverter.conver(menuList);
	}

	public void setMenuDao(MenuDao menuDao) {
		this.menuDao = menuDao;
	}

	public void setSiteDao(SiteDao siteDao) {
		this.siteDao = siteDao;
	}

	public void setFunctionDao(FunctionDao functionDao) {
		this.functionDao = functionDao;
	}

	public void setSiteFunctionDao(SiteFunctionDao siteFunctionDao) {
		this.siteFunctionDao = siteFunctionDao;
	}

	public void setRoleFunctionDao(RoleFunctionDao roleFunctionDao) {
		this.roleFunctionDao = roleFunctionDao;
	}
}
